package top.dyzmj.detty.core.buffer;

import top.dyzmj.detty.core.exception.IllegalReferenceCountException;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
 * 描述: 对引用计数的ByteBuf实现的抽象基类
 *
 * @author dongYu
 * @date 2021/11/19
 */
public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {

	private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater;

	static {
		refCntUpdater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
	}

	private volatile int refCnt = 1;

	/**
	 * 构造方法
	 *
	 * @param maxCapacity 最大容量
	 */
	protected AbstractReferenceCountedByteBuf(int maxCapacity) {
		super(maxCapacity);
	}

	@Override
	public int refCnt() {
		return refCnt;
	}

	/**
	 * 由直接设置缓冲区引用计数的子类，此处使用的是一种不安全操作
	 */
	protected final void setRefCnt(int refCnt) {
		this.refCnt = refCnt;
	}

	@Override
	public ByteBuf retain() {
		for (; ; ) {
			int refCntTmp = this.refCnt;
			if (refCntTmp == 0) {
				throw new IllegalReferenceCountException(0, 1);
			}
			if (refCntTmp == Integer.MAX_VALUE) {
				throw new IllegalReferenceCountException(Integer.MAX_VALUE, 1);
			}
			if (refCntUpdater.compareAndSet(this, refCntTmp, refCntTmp + 1)) {
				break;
			}
		}
		return this;
	}

	@Override
	public ByteBuf retain(int increment) {
		if (increment <= 0) {
			throw new IllegalArgumentException("increment: " + increment + " (expected: > 0)");
		}

		for (; ; ) {
			int refCntTmp = this.refCnt;
			if (refCntTmp == 0) {
				throw new IllegalReferenceCountException(0, increment);
			}
			if (refCntTmp > Integer.MAX_VALUE - increment) {
				throw new IllegalReferenceCountException(refCntTmp, increment);
			}
			if (refCntUpdater.compareAndSet(this, refCntTmp, refCntTmp + increment)) {
				break;
			}
		}
		return this;
	}


}
